package com.xyh.transaction.utils;

import com.xyh.transaction.common.GoodsCondition;
import com.xyh.transaction.entity.vo.GoodsVo;
import com.xyh.transaction.entity.vo.ImageVo;
import com.xyh.transaction.exception.BusinessException;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

public class MappingUtil {

    private static final ModelMapper MODEL_MAPPER = new ModelMapper();

//    public static <S, T> void addDynamicMappingRule(Class<S> sourceClass, Class<T> targetClass) {
//        // 在运行时动态添加映射规则
//        TypeMap<S, T> typeMap = modelMapper.createTypeMap(sourceClass, targetClass);
//
//        // 如果 sourceClass 是 User 类，且存在名为 gender 的枚举字段，则使用 enumConverter 进行映射
//        if (sourceClass == User.class && hasGenderField(sourceClass)) {
//            typeMap.addMappings(new PropertyMap<S, T>() {
//                protected void configure() {
//                    map().setGender(source.getGender().ordinal());
//                    map().setStatus(source.getStatus().ordinal());
//                }
//            });
//        }
//    }

    private static boolean hasGenderField(Class<?> sourceClass) {
        try {
            // 判断类中是否存在名为 gender 的字段
            sourceClass.getDeclaredField("gender");
            return true;
        } catch (NoSuchFieldException e) {
            return false;
        }
    }

    public static <S, T> List<T> mapList(Collection<S> sourceList, Class<T> targetClass) {
        // 严格匹配 否则会出现驼峰匹配不符合要求
        MODEL_MAPPER.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return sourceList.stream()
                .map(source -> mapObject(source, targetClass))
                .collect(Collectors.toList());
    }

    public static <S, T> T mapObject(S source, Class<T> targetClass) {
//        addDynamicMappingRule(source.getClass(),targetClass);
        MODEL_MAPPER.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return MODEL_MAPPER.map(source, targetClass);
//        try {
//            T target = targetClass.getDeclaredConstructor().newInstance();
//
//            for (Field sourceField : source.getClass().getDeclaredFields()) {
//                try {
//                    Field targetField = targetClass.getDeclaredField(sourceField.getName());
//                    sourceField.setAccessible(true);
//                    targetField.setAccessible(true);
//                    targetField.set(target, sourceField.get(source));
//                } catch (NoSuchFieldException ignored) {
//                    // Ignore fields that don't exist in the target class
//                }
//            }
//
//            return target;
//        } catch (Exception e) {
//            throw new RuntimeException("Error mapping objects", e);
//        }
    }

    public static GoodsVo melisearchResultMapToGoodsVo(Map<String, Object> map) {
        GoodsVo goodsVo = new GoodsVo();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");

        // updateTime
        Object updateTimeObj = map.get("updateTime");
        if (updateTimeObj != null) {
            goodsVo.setUpdateTime(LocalDateTime.parse(updateTimeObj.toString(), formatter));
        }

        // categoryName
        Object categoryNameObj = map.get("categoryName");
        if (categoryNameObj != null) {
            goodsVo.setCategoryName(categoryNameObj.toString());
        }

        // picture
        Object pictureObj = map.get("picture");
        if (pictureObj != null) {
            goodsVo.setPicture(pictureObj.toString());
        }

        // pictures
        Object picturesObj = map.get("pictures");
        if (picturesObj != null && picturesObj instanceof ArrayList) {
            ArrayList<Map<String, Object>> data = (ArrayList<Map<String, Object>>) picturesObj;
            List<ImageVo> pictures = data.stream().map(p -> {
                ImageVo imageVo = new ImageVo();
                Object nameObj = p.get("name");
                Object urlObj = p.get("url");
                if (nameObj != null && urlObj != null) {
                    imageVo.setName(nameObj.toString());
                    imageVo.setUrl(urlObj.toString());
                    return imageVo;
                } else {
                    return null; // or handle as needed
                }
            }).filter(Objects::nonNull).collect(Collectors.toList());
            goodsVo.setPictures(pictures);
        }

        // condition
        Object conditionObj = map.get("condition");
        if (conditionObj != null) {
            try {
                goodsVo.setCondition(GoodsCondition.valueOf(conditionObj.toString()));
            } catch (IllegalArgumentException e) {
                // handle if the condition value is not valid
                throw new BusinessException("解析meilisearch获取的商品数据异常！",e);
            }
        }

        // createBy
        Object createByObj = map.get("createBy");
        if (createByObj != null) {
            try {
                goodsVo.setCreateBy(Double.valueOf(createByObj.toString()).intValue());
            } catch (NumberFormatException e) {
                // handle if createBy value is not convertible to int
                throw new BusinessException("解析meilisearch获取的商品数据异常！",e);
            }
        }

        // createTime
        Object createTimeObj = map.get("createTime");
        if (createTimeObj != null) {
            goodsVo.setCreateTime(LocalDateTime.parse(createTimeObj.toString(), formatter));
        }

        // updateBy
        Object updateByObj = map.get("updateBy");
        if (updateByObj != null) {
            try {
                goodsVo.setUpdateBy(Double.valueOf(updateByObj.toString()).intValue());
            } catch (NumberFormatException e) {
                // handle if updateBy value is not convertible to int
                throw new BusinessException("解析meilisearch获取的商品数据异常！",e);
            }
        }

        // price
        Object priceObj = map.get("price");
        if (priceObj != null) {
            try {
                goodsVo.setPrice(new BigDecimal(priceObj.toString()));
            } catch (NumberFormatException e) {
                // handle if price value is not convertible to BigDecimal
                throw new BusinessException("解析meilisearch获取的商品数据异常！",e);
            }
        }

        // name
        Object nameObj = map.get("name");
        if (nameObj != null) {
            goodsVo.setName(nameObj.toString());
        }

        // id
        Object idObj = map.get("id");
        if (idObj != null) {
            try {
                goodsVo.setId(Double.valueOf(idObj.toString()).intValue());
            } catch (NumberFormatException e) {
                // handle if id value is not convertible to int
                throw new BusinessException("解析meilisearch获取的商品数据异常！",e);
            }
        }

        // stock
        Object stockObj = map.get("stock");
        if (stockObj != null) {
            try {
                goodsVo.setStock(Double.valueOf(stockObj.toString()).intValue());
            } catch (NumberFormatException e) {
                // handle if stock value is not convertible to int
                throw new BusinessException("解析meilisearch获取的商品数据异常！",e);
            }
        }

        // categoryId
        Object categoryIdObj = map.get("categoryId");
        if (categoryIdObj != null) {
            try {
                goodsVo.setCategoryId(Double.valueOf(categoryIdObj.toString()).intValue());
            } catch (NumberFormatException e) {
                // handle if categoryId value is not convertible to int
                throw new BusinessException("解析meilisearch获取的商品数据异常！",e);
            }
        }

        // desc
        Object descObj = map.get("desc");
        if (descObj != null) {
            goodsVo.setDesc(descObj.toString());
        }

        return goodsVo;
    }
}
